package no.uib.hplims.tools.columngenerators;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import uk.ac.ebi.kraken.interfaces.uniprot.features.Feature;
import uk.ac.ebi.kraken.interfaces.uniprot.features.FeatureLocation;
import no.uib.hplims.jobs.Pair;
import no.uib.hplims.models.BlastInfo;
import no.uib.hplims.models.Peptide;

import com.vaadin.ui.Label;
import com.vaadin.ui.Table;
import com.vaadin.ui.Table.ColumnGenerator;

public class SequenceModificationColumnGenerator implements ColumnGenerator {

	private static final long serialVersionUID = -6716424415846681416L;

	private Collection<?> selectedModifications = null;

	public SequenceModificationColumnGenerator(Collection<?> selectedMods) {
		selectedModifications = selectedMods;
	}

	public Object generateCell(Table source, Object itemId, Object columnId) {
		Peptide p = (Peptide) itemId;
		Label seqLabel;
		BlastInfo bh = p.getSelectedProtein();
		if (bh != null) {
			seqLabel = new Label(sequenceHighlightModifications(p));
			seqLabel.setContentMode(Label.CONTENT_XHTML);
		} else {
			seqLabel = new Label(p.getPeptideSequence());
		}
		return seqLabel;
	}


	/**
	 * Generate an XHTML string representing a peptide sequence with known
	 * modifications highlighted in red.
	 *
	 * @param p
	 *            The peptide
	 * @return The XHTML string
	 */
	private String sequenceHighlightModifications(Peptide p) {
		String xHtmlRepr = "";
		// Get start position for the peptide sequence in the protein sequence
		int peptideStart = p.getSelectedProtein().getPeptideStart();
		// List of start and end positions for know modifications
		List<Pair> modPositions = new ArrayList<Pair>();
		for (Feature f : p.getSelectedProtein().getKnownModifications()) {

			// Skip unwanted modifications
			if (selectedModifications != null) {
				if ((!selectedModifications.contains("Site") && f.getType()
						.getName().equalsIgnoreCase("SITE"))
						|| (!selectedModifications.contains("Variant") && f
								.getType().getName()
								.equalsIgnoreCase("VARIANT"))
						|| (!selectedModifications
								.contains("Modified residues") && f.getType()
								.getName().equalsIgnoreCase("MOD_RES"))) {
					// Skip
					continue;
				}
			}
			FeatureLocation fl = f.getFeatureLocation();
			/*
			 * Add start and end positions for the modification Indices are
			 * transformed from protein to peptide positions
			 */
			Pair pair = new Pair(fl.getStart() - peptideStart, fl.getEnd()
					- peptideStart);
			modPositions.add(pair);
		}
		/*
		 * Go through every amino acid in the sequence to see if there is a
		 * known modification in that position
		 */
		for (int i = 0; i < p.getPeptideSequence().length(); i++) {
			// Length of longest found modification in this position
			int longestMod = 0;
			Pair longestModPair = null;
			/*
			 * Go through all modifications to find the modification that spans
			 * the most amino acids.
			 */
			for (Pair pair : modPositions) {
				int start = (Integer) pair.getFirst();
				if (start == i) {
					int end = (Integer) pair.getSecond();
					int length = end - start;
					length++;
					// System.out.println("---" + p.getPeptideSequence() +
					// "---");
					// System.out.println("Modification in position " + i);
					// System.out.println("Mod start: " + start + " Mod end: " +
					// end);
					// System.out.println("Length: " + length);
					if (length >= longestMod) {
						longestMod = length;
						longestModPair = pair;
					}
				}
			}

			if (longestMod == 0) {
				// No modification
				xHtmlRepr += p.getPeptideSequence().charAt(i);
			} else if (longestMod == 1) {
				// Modification of length 1
				xHtmlRepr += "<font color=\"red\">"
						+ p.getPeptideSequence().charAt(i) + "</font>";
			} else if (longestMod > 1) {
				// Modification of length > 1
				if (longestModPair != null) {
					int start = (Integer) longestModPair.getFirst();
					int end = (Integer) longestModPair.getSecond();
					if (p.getPeptideSequence().length() >= end + 1) {
						xHtmlRepr += "<font color=\"red\">"
								+ p.getPeptideSequence().substring(start,
										end + 1) + "</font>";
					} else {
						xHtmlRepr += "<font color=\"red\">"
								+ p.getPeptideSequence().substring(start)
								+ "</font>";
					}
				}
				/*
				 * Increment index to skip ahead in the sequence. No need to
				 * check for modification in positions that have already been
				 * marked as containing a known modification
				 */
				i += longestMod-1;
			}
		}
		return xHtmlRepr;
	}

	public void updateSelectedMods(Collection<?> selectedModifications2) {
		this.selectedModifications = selectedModifications2;
	}

}
